package com.loveprogrammer.lowercode.dna.def;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.loveprogrammer.lowercode.dna.instance.bo.Inst;
import com.loveprogrammer.lowercode.dna.instance.bo.Va;
import com.loveprogrammer.lowercode.dna.common.CodeDefConst;
import com.loveprogrammer.lowercode.dna.common.DataType;
import com.loveprogrammer.lowercode.dna.common.OperationFlagEnum;
import com.loveprogrammer.lowercode.dna.instance.bo.Cell;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class DnaTool {

    public static Cell dna2Cell(String instType, Dna dna){
        Cell cell = singelDna2Cell(instType,dna);
        for (Dna child : dna.getChildren()) {
            Inst childInst = new Inst(instType,child,cell);
            cell.addChildInst(dna.getDnaName(),dna.getDnaCode() ,childInst);
        }
        return cell;
    }

    private static Cell singelDna2Cell(String instType, Dna dna) {
        if(dna == null){
            return null;
        }
        Cell cell = null;
        if(instType.equals(CodeDefConst.INST_TYPE_DEFAULT))
            cell = new Cell();
        cell.setOperationFlag(OperationFlagEnum.ADD.getCode());
        for (Vd vd : dna.getVds()) {
            Va va = vd2Va(vd);
            cell.getVas().put(vd.getVdName(),va);
        }
        return cell;
    }

    private static Va vd2Va(Vd vd) {
        if(vd == null){
            throw new RuntimeException("属性定义vd不能为空");
        }
        Va va = new Va();
        va.setCode(vd.getVdCode());
        va.setName(vd.getVdName());
        String dataType = vd.getDataType();
        va.setDataType(vd.getDataType());
        if(dataType.equals(DataType.DATA_TYPE_INT)){
            va.setValue(0);
        }else if(dataType.equals(DataType.DATA_TYPE_LONG)){
            va.setValue(0L);
        }else if(dataType.equals(DataType.DATA_TYPE_FLOAT)){
            va.setValue(0.0);
        }
        return va;
    }

    public static <T> Inst object2Inst(List<T> objs, Dna dna) {
        if(objs == null)
            return null;
        Inst inst = new Inst(CodeDefConst.INST_TYPE_DEFAULT, dna, null);
        for (Object obj : objs) {
            if(obj == null) continue;

            Cell cell = dna2Cell(CodeDefConst.INST_TYPE_DEFAULT, dna);
            inst.addCell(cell);
            // 调用函数 objectField2Va将对象每一个属性转换为 Cell 对象的下 Va 对象。
            for (Vd vd : dna.getVds()) {
               Va va = cell.getVaByName(vd.getVdName());
               objectField2Va(obj, vd.getVdName(), va);
            }

            for (Dna childDna : dna.getChildren()) {
                List childObjs = getListFieldOfObject(obj,childDna.getDnaName());
                if(childObjs != null) {
                    Inst childInst = object2Inst(childObjs, childDna);
                    cell.addChildInst(childInst);
                }
            }
            // 是递归的
            if(dna.isCursive()) {
                List childObjs = getListFieldOfObject(obj,dna.getDnaName());
                if(childObjs != null) {
                    Inst childInst = object2Inst(childObjs, dna);
                    cell.addChildInst(childInst);
                }
            }

        }
        return inst;
    }


    private static List getListFieldOfObject(Object obj, String dnaName) {
        // 通过dnaName获得子List数据
        JSONObject jsonFrom = JSONObject.from(obj);
        JSONArray jsonArray = jsonFrom.getJSONArray(dnaName);
        List<Object> list = jsonArray.toList(Object.class);
        return list;
    }

    // 将obj中的字段转成va
    private static void objectField2Va(Object obj, String vdName, Va va) {

        JSONObject jsonFrom = JSONObject.from(obj);
        Object value = jsonFrom.get(vdName);
        va.setValue(value);
    }


    public static <T> Inst object2Inst(List<T> objs, Dna dna
            , Map<String,String> vdNameMap, Set<String> ignoreVdNames){

        if(objs == null) return null;
        Inst inst = new Inst(CodeDefConst.INST_TYPE_DEFAULT,dna,null);
        String vdName;
        for (Object obj : objs) {
            if(obj == null) continue;
            Cell cell = dna2Cell(CodeDefConst.INST_TYPE_DEFAULT, dna);
            inst.addCell(cell);

            for (Vd vd : dna.getVds()) {
                if(ignoreVdNames.contains(vd.getVdName())) continue;
                Va va = cell.getVaByName(vd.getVdName());
                vdName = vdNameMap.get(vd.getVdName());
                if(vdName == null || "".equals(vdName)) {
                    vdName = vd.getVdName();
                }
                objectField2Va(obj,vdName,va);
            }

            for (Dna childDna : dna.getChildren()) {
                if(ignoreVdNames.contains(childDna.getDnaName())) continue;

                vdName = vdNameMap.get(childDna.getDnaName());
                if(vdName == null) vdName = childDna.getDnaName();
                List childObjs = getListFieldOfObject(obj, vdName);
                if(childObjs != null) {
                    Inst childInst = object2Inst(childObjs, childDna, vdNameMap, ignoreVdNames);
                    cell.addChildInst(childInst);
                }
            }


            if(dna.isCursive() && !ignoreVdNames.contains(dna.getDnaName())) {
                vdName = vdNameMap.get(dna.getDnaName());
                if(vdName == null) vdName = dna.getDnaName();
                List childObjs = getListFieldOfObject(obj, vdName);
                if(childObjs != null) {
                    Inst childInst = object2Inst(childObjs, dna, vdNameMap, ignoreVdNames);
                    cell.addChildInst(childInst);
                }
            }
        }
        return inst;
    }
}
